home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
PROGRAMM
/
DB_CLIPP
/
2614.ZIP
/
TBROWSE.ZIP
/
TBROWSE_.TXT
Wrap
Text File
|
1990-11-13
|
43KB
|
1,594 lines
Overview
What Are TBROWSE Objects ?
TBROWSE objects are basically a collection of definitions. The
definitions being:
1. The size of the TBROWSE object
2. The number of columns (TBCOLUMN objects)
3. The colours for the columns (depending on their values)
4. Headings and footings for columns
5. Separators of Columns/Headings/Footings
6. How to move around the TBROWSE object, column to column and
row to row.
TBROWSE objects are created using the class functions
TBROWSENEW() and TBROWSEDB().
TBROWSE objects are built up by specifying what are called
Exported Instance Variables and manipulated using Exported
Instance Methods.
Exported Instance Variables are a means of referencing certain
elements of the TBROWSE object. They have been given names such
as nTop,nLeft,nBottom and nRight (the screen coordinates of the
TBROWSE object) which make them more readable.
Exported Methods are a means of performing certain actions on a
TBROWSE object. As with the instance variables the methods have
meaningful names. The methods will act upon the values contained
in the TBROWSE instance variables and the TBCOLUMN instance
variables for each column in the TBROWSE object.
The columns for TBROWSE objects are classed as TBCOLUMN objects
which themselves have exported instance variables. These TBCOLUMN
objects are added to the TBROWSE object. Each column being
another set of rules for that particular column.
What can TBROWSE Objects Be Used For ?
TBROWSE objects are one of the most powerful features added to
Clipper 5.0. They enable browsing of data sets be they .DBF
files, arrays, memory variables or directory information. Similar
but more powerful than the functions DBEDIT() and ACHOICE().
TBROWSE objects offer the facility of being able to display any
information in a table-type display with headings,footing and
each column separated by any character, much the same as DBEDIT()
but can DBEDIT() perform such things as Scoping data sets, moving
columns, inserting new columns or even work on an array ? Not
very easily. TBROWSE objects can.
Once mastered TBROWSE objects will become a regular part of every
programmers applications.
For the majority of this document you should assume that we are
applying TBROWSE objects on .DBF files but keep an open mind. As
you read you will instinctively think 'What ? You can do that ?
Hang on...what if ...' You know what we mean.
Creating TBROWSE Objects
TBROWSE Classes
Class Functions
TBROWSE Class Function: TBROWSENEW()
Syntax: TBROWSENEW( top , left , bottom , right )
Where: top,left,bottom,right are the screen coordinates in which
the TBROWSE object is to be used in.
Purpose: TBROWSENEW() will create an empty TBROWSE object without
containing any code blocks for the skipBlock,goBottomBlock and
goTopBlock exported instance variables, (see TBROWSE exported
instance variables for descriptions), or columns.
To create a TBROWSE object either the TBROWSENEW() or the
TBROWSEDB() functions must be used.
To use this function the return value, the TBROWSE object, must
be captured. For example:
TBROWSENEW(10,10,20,60)
Will return a TBROWSE object but it cannot be used as it's return
value has not be captured so you should use:
object_name := TBROWSENEW(10,10,20,60)
This may seem obvious but you will be surprised how many people
forget to do this.
SEE ALSO: TBROWSEDB(), TBROWSE Exported Instance Variables
TBROWSE Class Function: TBROWSEDB()
Syntax: TBROWSEDB( top , left , bottom , right )
Where: top,left,bottom,right are the screen coordinates in which
the TBROWSE object is to be used in.
Purpose: TBROWSEDB() will create an empty TBROWSE object
containing default code blocks for the skipBlock,goBottomBlock
and goTopBlock exported instance variables, (see TBROWSE exported
instance variables for descriptions), but without any columns.
To create a TBROWSE object either the TBROWSEDB() or the
TBROWSENEW() functions must be used.
To use this function the return value, the TBROWSE object, must
be captured. For example:
TBROWSEDB(10,10,20,60)
Will return a TBROWSE object but it cannot be used as it's return
value has not be captured so you should use:
object_name := TBROWSEDB(10,10,20,60)
This may seem obvious but you will be surprised how many people
forget to do this.
SEE ALSO: TBROWSENEW(), TBROWSE Exported Instance Variables
Assigning Instance Variables and Performing Exported Methods
When ever you wish to assign an instance variable or perform an
exported method on an object the following syntax must be
observed.
Assigning an instance variable
object name:instance variable := value
Performing an exported method
object name:method name(parameters)
As long as these simple rules are used you can't go wrong.
Exported Instance Variables
TBROWSE Exported Instance Variable: autoLite
autoLite is a user assignable instance variable which must
contain a logical value.
If the value of autoLite is .T. (true) the TBROWSE exported
method stabilize() will automatically highlight the current cell
of the TBROWSE object as part of the stabilization process. Which
obviously means that if autoLite contains a value of .F. (false)
highlighting of the current cell will not be performed.
By default the value of autoLite is .T. .
Example
// Turn off auto highlighting
object:autoLite := .F.
TBROWSE Exported Instance Variable: cargo
cargo is a user assignable instance variable that is provided as
a user definable slot which may contain a value of any data type.
The information held in cargo will not be used by any of the
TBROWSE exported methods so you must write the code to use it.
Implementing the cargo instance variable will give the TBROWSE
object a great deal more power as it can be used to contain
comments, help, a GET list or even another TBROWSE object.
Example
// Assigning a character string to cargo
object:cargo := 'Hello World'
TBROWSE Exported Instance Variable: colCount
colCount contains a numeric value being the total number of
columns that have been added to the TBROWSE object using the
exported method addColumn().
This instance variable is not assignable so don't try to.
Example
// Retrieving the number of columns in a TBROWSE object
Column_Count := object:colCount
TBROWSE exported Instance Variable: colorSpec
colorSpec is a user assignable instance variable which contains a
character string representing a colour table for the TBROWSE
display. By default the value returned by SETCOLOR() will be
used. This instance variable is also used as a lookup table later
by the TBCOLUMN exported instance variables defColor and
colorBlock.
The colour table string would be created like this:
color_string := 'W/N , N/W , GR+/B , R*/BG'
Table position 1 ─┘ │ │ └ Table position 4
Table position 2 ─┘ └─ Table position 3
The colour string table can have as many colour combinations as
required. Each colour specification must be separated by a comma.
Example
// Assigning five colours combinations
object:colorSpec := { 'W/N' , 'N/W' , 'R/B' , 'B/R' , 'GR+/BG' }
// Index position 1 2 3 4 5
TBROWSE Exported Instance Variable: colPos
colPos is a numeric user assignable instance variable used to set
or retrieve the current column position of the TBROWSE object.
Columns are number from 1 to x where 1 is the leftmost column.
If you set colPos to a different 'visible' column the cursor
position will change. If you set colPos to a column that is not
visible you must use the configure() exported method to force the
refreshing of the display.
Example
// Changing the column where the highlight bar is
object:colPos := 5 // Go to the 5th column
object:configure() // Reconfigure everything incase column
// is not on the screen
TBROWSE Exported Instance Variable: colSep
colSep is a user assignable instance variable used to define the
character(s) to be used by default to separate each column in the
TBROWSE display.
The value set in colSep will be overridden if the colSep TBCOLUMN
instance variable is specified.
Example
// Assign ' ║ ' to be the default column separators
object:colSep := ' ║ '
TBROWSE Exported Instance Variable: freeze
freeze is a user assignable instance variable containing a
numeric value which specifies the number of data columns that are
to be frozen from the leftmost column. Setting this instance
variable will force the number of columns specified to be
constantly displayed leaving other columns still being accessible
by panning the display.
Note: If you specify a number high enough so that to disable
other non-frozen columns never to be able to displayed by panning
the display one or more of the frozen columns may not become
frozen.
Example
// Freeze the first three columns
object:freeze := 3
TBROWSE Exported Instance Variable: goBottomBlock
goBottomBlock is a user assignable instance variable containing
the code block to be evaluated whenever the goBottom() exported
method is encountered.
When using the TBROWSEDB() class function to create the TBROWSE
object the code block contained in goBottomBlock will call a user
defined function that performs the GOTO BOTTOM command.
Note: If anything other than a code block is assigned to
goBottomBlock an Internal Error 612 will occur.
Example
// Issuing a go bottom
object:goBottomBlock := {||MyGoBottom()}
Function MyGoBottom()
GOTO BOTTOM
Return NIL
TBROWSE Exported Instance Variable: goTopBlock
goTopBlock is a user assignable instance variable containing the
code block to be evaluated whenever the goTop() exported method
is encountered.
When using the TBROWSEDB() class function to create the TBROWSE
object the code block contained in goTopBlock will call a user
defined function that performs the GOTO TOP command.
Note: If anything other than a code block is assigned to
goTopBlock an Internal Error 612 will occur.
Example
// Issuing a go top
object:goTopBlock := {||MyGoTop()}
Function MyGoTop()
GOTO TOP
Return NIL
TBROWSE Exported Instance Variable: headSep
headSep is a user assignable instance variable used to define the
character(s) to be used by default to separate each column for
it's heading in the TBROWSE display.
The value set in headSep will be overridden if the headSep
TBCOLUMN instance variable is specified.
Example
// Assign '─╥─' to be the default header separators
object:headSep := '─╥─'
TBROWSE Exported Instance Variable: hitBottom
hitBottom is an user assignable instance variable containing a
logical value. hitBottom will be set to .T. (true) if an attempt
was made to navigate past the end of the available data otherwise
it contains a .F. (false).
One of the biggest uses of hitBottom is the ability to trap for
invalid records in scoped TBROWSEs.
Note: Although hitBottom is assignable it's value may be changed
by the stabilize() exported method.
Example
// Beep if tried to move past the end of the scoped data
If object:hitBottom
? Chr(7)
Endif
TBROWSE Exported Instance Variable: hitTop
hitTop is an user assignable instance variable containing a
logical value. hitBottom will be set to .T. (true) if an attempt
was made to navigate past the beginning of the available data
otherwise it contains a .F. (false).
One of the biggest uses of hitTop is the ability to trap for
invalid records in scoped TBROWSEs.
Note: Although hitTop is assignable it's value may be changed by
the stabilize() exported method.
Example
// Beep if tried to move past the beginning of the scoped data
If object:hitTop
? Chr(7)
Endif
TBROWSE Exported Instance Variables: nBottom,nLeft,nRight,nTop
nBottom, nLeft, nRight and nTop are all assignable instance
variables containing numeric values for defining the row and
column positions of the TBROWSE display.
Examples
// Moving the TBROWSE screen up 5 rows and left 5 columns
object := TBROWSEDB(10,10,20,60)
object:nBottom := 15
object:nLeft := 5
object:nRight := 55
object:nTop := 5
object:configure() // To redisplay everything correctly
// Same as doing object := TBROWSEDB(5,5,15,55)
TBROWSE Exported Instance Variable: rowCount
rowCount contains a numeric value being the total number of
visible rows.
This instance variable is not assignable so don't try to.
Example
// Retrieving the number if visible data rows
data_rows := object:rowCount
TBROWSE Exported Instance Variable: rowPos
rowPos is a numeric user assignable instance variable used to set
or retrieve the current data row position of the TBROWSE object.
Columns are number from 1 to x where 1 is the topmost data row.
Note: Screen rows, headings, footings or separators are not
regarded as data rows.
Example
// Move the highlight bar down 5 rows
object:rowPos ++5
SKIP 5 // To retrieve the correct data
object:refreshCurrent() // To display correct information
TBROWSE Exported Instance Variable: skipBlock
skipBlock is a user assignable instance variable containing a
code block to be evaluated whenever the up(), down(), pageUp(),
pageDown() TBROWSE cursor movement methods are encountered or
during the stabilizing process using the stabilize() exported
method.
The code block contained in skipBlock should receive one
parameter, as it is always passed one. This parameter contains
the number of rows to move, positive means in a downward
direction and negative upward. The code block should then call a
user defined function that passes this received parameter and any
other you may wish to pass. For example a condition for a scope.
All checking of data scopes is then performed inside this user
defined function and must return a numeric value in order for the
TBROWSE object to function correctly. This return value should be
the number of rows the skipBlock was able to actually move. If
the return value equals the number of rows requested to move then
both hitBottom and hitTop instance variables will be set to .F.
(false). If not then either hitBottom or hitTop will be set to
.T. (true) meaning that an attempt was made to move outside of
the scoped data.
skipBlock is the most powerful exported instance variable in
TBROWSE object. It should be used with care otherwise spurious
results could and probably will occur.
Note: If a data type other than a code block is assigned to
skipBlock an Internal Error 612 will occur.
Examples
See the SKIPPER() Function in the TBDEMO.PRG in your
\CLIPPER5\SOURCE\SAMPLE directory.
TBROWSE Exported Instance Variable: stable
stable is a user assignable instance variable containing a
logical value represent whether the TBROWSE is stable or not. A
TBROWSE is considered stable when all data has been retrieved and
displayed, the data source has been correctly re-positioned to
the value at the browse cursor and the current cell has been
highlighted (if required).
Note: If any Cursor Movement Method is used the stable instance
variable is automatically set to .F. (false)
Examples
// Check to see if the TBROWSE object is stable
Do While .T.
object:stabilize()
If object:stable
? 'Object Stable'
Exit
Else
? 'Object Not Stable'
Endif
Enddo
Exported Methods
Cursor Movement Methods
TBROWSE Cursor Movement Method: down()
down() forces a request to move down one row in the TBROWSE
display. The code block contained in the skipBlock instance
variable is then evaluated passing 1 as a parameter.
If moving down one row forces a request to move past the end of
the scope the hitBottom instance variable will then be set to .T.
(true).
Example
object:down()
TBROWSE Cursor Movement Method: end()
end() forces the TBROWSE cursor to be displayed on the rightmost
visible column. If the autoLite instance variable is set to .T.
(true) the old column position will be automatically
dehighlighted and the new column to be highlighted.
Example
object:end()
TBROWSE Cursor Movement Method: goBottom()
goBottom() forces evaluation of the code block contained in the
goBottomBlock instance variable. Row positions will be updated to
reflect this in the following way.
If the last scoped row is not visible or the last scoped record
is displayed and is on the data row the row position (rowPos
instance variable) will be set to the last data row position
otherwise it will be set to the data row position where the last
scoped data row is currently situated.
Example
object:goBottom()
TBROWSE Cursor Movement Method: goTop()
goTop() forces evaluation of the code block contained in the
goTopBlock instance variable. Row positions will be updated to 1.
Example
object:goTop()
TBROWSE Cursor Movement Method: home()
home() forces the TBROWSE cursor to be displayed on the leftmost
visible column. If the autoLite instance variable is set to .T.
(true) the old column position will be automatically
dehighlighted and the new column to be highlighted.
Example
object:home()
TBROWSE Cursor Movement Method: left()
left() forces the TBROWSE cursor to be displayed on the column
position one left of the current column position. If the autoLite
instance variable is set to .T. (true) the old column position
will be automatically dehighlighted and the new column to be
highlighted. If the new column position is not visible the
display is then panned to the left.
Example
object:left()
TBROWSE Cursor Movement Method: pageDown()
pageDown() forces a request to move the last visible data row in
the TBROWSE display to the first. The code block contained in the
skipBlock instance variable is then evaluated passing then number
of visible data rows -1 as a parameter.
If moving up x number of rows forces a request to move past the
end of the scope the hitBottom instance variable will then be
set to .T. (true).
Example
object:pageDown()
TBROWSE Cursor Movement Method: pageUp()
pageUp() forces a request to move the first visible data row in
the TBROWSE display to the last. The code block contained in the
skipBlock instance variable is then evaluated passing the -number
of visible data rows -1 as a parameter.
If moving down x number of rows forces a request to move past the
end of the scope the hitBottom instance variable will then be
set to .T. (true).
Example
object:pageUp()
TBROWSE Cursor Movement Method: panEnd()
panEnd() forces the current column position (colPos) to be set to
the last available data column and displays that column as the
rightmost column. Columns to the left of the last position are
also drawn if necessary.
Example
object:panEnd()
TBROWSE Cursor Movement Method: panHome()
panHome() forces the current column position (colPos) to be set
to the first available data column and displays that column as
the leftmost column. Columns to the right of the last position
are also drawn if necessary.
Example
object:panHome()
TBROWSE Cursor Movement Method: panLeft()
panLeft() will pan the display one or more positions to the left
without changing the TBROWSE cursor position (if possible)
causing the rightmost column (possibly more) to be removed from
the display.
Example
object:panLeft()
TBROWSE Cursor Movement Method: panRight()
panRight() will pan the display one or more positions to the
right without changing the TBROWSE cursor position (if possible)
causing the leftmost column (possibly more) to be removed from
the display.
Example
object:panRight()
TBROWSE Cursor Movement Method: right()
right() forces the TBROWSE cursor to be displayed on the column
position one right of the current column position. If the
autoLite instance variable is set to .T. (true) the old column
position will be automatically dehighlighted and the new column
to be highlighted. If the new column position is not visible the
display is then panned to the right.
Example
object:right()
TBROWSE Cursor Movement Method: up()
up() forces a request to move up one row in the TBROWSE display.
The code block contained in the skipBlock instance variable is
then evaluated passing -1 as a parameter.
If moving down one row forces a request to move past the
beginning of the scope the hitTop instance variable will then be
set to .T. (true).
Example
object:up()
Miscellaneous Methods
TBROWSE Miscellaneous Method: addColumn(column)
addColumn() add a new TBCOLUMN object previously created with the
TBColumnNew() TBCOLUMN class function to a TBROWSE object.
Example
// Add All Fields Of A .DBF into a TBROWSE Object
Select 1
Use .DBF
object:=TBROWSEDB(10,10,20,60)
For i = 1 To FCOUNT()
column := TBColumnNew(Fieldname(i),;
FIELDWBLOCK(Fieldname(i),1))
object:addColumn(column)
Next i
TBROWSE Miscellaneous Method: colorRect(rectangle,colours)
colorRect() will cause the change of colour for a group of cells
defined in the parameter <rectangle> to the colour combination
specified in the parameter <colours>.
rectangle should be formatted in the following way:
{ top data row ,;
leftmost data column ,;
bottom data row ,;
rightmost data column }
colours should be formatted in the following way:
{ normal colour number , highlighted colour number }
The numbers specified in this array will correspond to positions
in the colorSpec instance variable.
Cells coloured using the colorRect() method visible or not, will
matin these new colours until they are scrolled out of the
TBROWSE object up and down only. Panning the TBROWSE display does
not affect the colours.
Example
// Colour for cells row 3 - col 5 to row 6 - col 10 in
// colour 3 and 4 of the colorSpec instance variable
object:colorSpec := { 'W/N' , 'N/W' , 'R/B' , 'B/R' }
object:colorRect( { 3 , 4 , 6 , 10 } , { 3 , 4 } )
TBROWSE Miscellaneous Method: configure()
configure() causes the TBROWSE object to re-examine all of it's
instance variables and TBCOLUMN objects. Depending on what it
finds it will then reconfigure it's internal settings. The method
would be used when one of the TBROWSEs' TBCOLUMN objects has been
modified directly. ie/ when a column has been
moved/inserted/deleted or had it's values changed.
Once this method has been changed a complete stablization will
need to be done to redisplay the correct information.
Example
// Change a columns width
new_column := getColumn(3)
newcolumn:width := 25
object:setColumn(3,new_column)
// configure object after directly modifying a TBCOLUMN object
object:configure()
TBROWSE Miscellaneous Method: deHilite()
deHilite() causes the current cell to be de-highlighted. If the
cell is already de-highlighted this method will de-highlight it
again.
deHilte() has been designed to be used when the autoLite instance
variable is set to .F. (false).
Example
object:deHilite()
TBROWSE Miscellaneous Method: getColumn(column number)
getColumn() will return the TBCOLUMN object for the TBROWSE
column specified in the parameter column number.
This method is extremely useful. It would be used to enable any
column to have it's value changed, be it it's colour, width,
heading etc. To replace the TBCOLUMN object when it has been
changed you would use the setColumn() method.
When used in conjunction with the setColumn() method it can be
used to swap the positions of columns in a TBROWSE object.
Example
// Change a columns width
new_column := getColumn(3)
newcolumn:width := 25
object:setColumn(3,new_column)
// configure object after directly modifying a TBCOLUMN object
object:configure()
TBROWSE Miscellaneous Method: hilite()
hilite() causes the current cell to be highlighted. If the cell
is already highlighted this method will highlight it again.
hilite() has been designed to be used when the autoLite instance
variable is set to .F. (false).
Example
object:hiLite()
TBROWSE Miscellaneous Method: refreshAll()
refreshAll() will cause all of the TBCOLUMN objects for a TBROWSE
to be marked internally as invalid. This means the they need
redisplaying.
When the next stabilization occurs all columns will be redrawn.
Example
// Refresh all columns
object:refreshAll()
TBROWSE Miscellaneous Method: refreshCurrent()
refreshCurrent() will cause the current TBCOLUMN object for a
TBROWSE to be marked internally as invalid. This means it needs
to be redisplayed.
When the next stabilization occurs the column will be redrawn.
Example
// Refresh Current Column
object:refreshCurrent()
TBROWSE Miscellaneous Method:
setColumn(column number,new column)
setColumn() will change the TBCOLUMN object for the TBROWSE
column specified in the parameter column number with the new
column contained in the parameter new column.
This method would be used to replace a TBCOLUMN object that has
been changed directly after receiving it using the getColumn()
method.
When used in conjunction with the getColumn() method it can be
used to swap the positions of columns in a TBROWSE object.
Example
// Change a columns width
new_column := getColumn(3)
newcolumn:width := 25
object:setColumn(3,new_column)
// configure object after directly modifying a TBCOLUMN object
object:configure()
TBROWSE Miscellaneous Method: stabilize()
stabilize() will perform an incremental stabilization of the
TBROWSE object. Each time this method is encountered a new part
of the stablization process is done.
The actions performed by stablization are:
1. Display of the TBROWSE object.
2. Display of each TBCOLUMN object visible or not.
3. Display of headings,footings,column/heading/footer separators.
4. Highlighting and dehighlighting of cells.
If the stablization has been successfully completed it will
return a .T. (true) otherwise a .F. (false) will be returned
indicating that there is still more to do.
Why would I want something that is not stable ?, I hear you ask.
Depending on the complexity of the TBROWSE object some
stabilizations may take longer than others. The stabilization has
been designed to be performed in steps to enable the
stabilization to be interrupted, by a keystroke for example.
Although if you press a key, which interrupts stabilization,
process that key, which may mean alterations to the TBROWSE
object, the next time the stabilize() method is encountered it
will simply start stabilizing from the new values of the TBROWSE
object and it's TBCOLUMN objects.
Example
// Keep stabilizing until stable or a key has been pressed
Do While !(object:stabilize())
nKey:=Inkey()
If !(nKey = 0)
Exit
Endif
Enddo
TBCOLUMN Classes
Class Functions
TBCOLUMN Class Function: TBColumnNew(heading, retrieval block)
TBColumnNew() returns a TBCOLUMN object that can be added to a
TBROWSE object. The parameters heading and retrieval block must
be passed in order for this function to work.
heading is a character string containing the heading for the
TBCOLUMN object. The value of heading is placed into the heading
exported instance variable.
retrieval block is a code block the returns the data to be
displayed. The value of retrieval block is placed into the block
exported instance variable.
All other instance variables may be assigned to the TBCOLUMN
object once the object has been created using the syntax
described earlier.
Example
// Add All Fields Of A .DBF into a TBROWSE Object
Select 1
Use .DBF
object:=TBROWSEDB(10,10,20,60)
For i = 1 To FCOUNT()
column := TBColumnNew(Fieldname(i),;
FIELDWBLOCK(Fieldname(i),1))
object:addColumn(column)
Next i
Exported Instance Variables
TBCOLUMN Exported Instance Variable: block
block is a user assignable instance variable whose type must be a
code block. The value returned by that code block will determine
what the TBCOLUMN object will actually display.
Note: If a value other than a code block is assigned to block an
Internal error 612 will occur.
Example
// Assign a new field
object:block := FIELDWBLOCK( 'Fieldname' , 'Alias' )
TBCOLUMN Exported Instance Variable: cargo
cargo is a user assignable instance variable that is provided as
a user definable slot which may contain a value of any data type.
The information held in cargo will not be used by any of the
TBROWSE exported methods so you must write the code to use it.
Implementing the cargo instance variable will give the TBROWSE
object a great deal more power as it can be used to contain
comments, help, a GET list or even another TBROWSE object.
Example
// Assign a character string to cargo
object:cargo := 'Hello World'
TBCOLUMN Exported Instance Variable: colorBlock
colorBlock is an assignable instance variable of code block data
type. The code block assigned to colorBlock should receive one
parameter being the data retrieved by the block instance
variable. Depending on the value received by the code block an
array of two elements both containing numeric values must be
returned. The values contained in the returned array are colour
index numbers used as to pull the colours from the TBROWSE
colorSpec instance variable.
Note: If colorBlock is specified it will override the value
contained in the defColor instance variable.
Example
// Give different colours for negative numbers
object:colorBlock := { |arg| If(arg < 0 ,{ 3 , 4 } ,{ 1 ,2 } ) }
TBCOLUMN Exported Instance Variable: colSep
colSep is a user assignable instance variable used to define the
character(s) to be used to separate the column TBCOLUMN object
from the next in the display.
The value set in colSep will override the value in the TBROWSE
colSep instance variable.
Example
object:colSep := ' ║ '
TBCOLUMN Exported Instance Variable: defColor
defColor is an assignable instance variable with a data type of
array containing two element being the colour index numbers of
the TBROWSE colorSpec instance variable. By default { 1 , 2 } is
assigned to defColor. The first color index number is the normal
colour, the second being the highlighted colour.
Note: If colour index number held in defColor will be overridden
if the colorBlock instance variable has been defined.
Example
// Use colours 1 and 2 for character otherwise use 3 and 4
If VALTYPE( EVAL( object:block ) ) = 'C'
object:defColor := { 1 , 2 }
Else
object:defColor := { 3 , 4 }
Endif
TBCOLUMN Exported Instance Variable: footing
footing is an assignable instance variable which when assigned
determines what to display as a footing for a TBCOLUMN object.
The footing will be displayed on the bottom row of the TBROWSE
object window. Specifying this instance variable will cause the
loss of one data row.
Example
object:footing := 'This is a footing'
TBCOLUMN Exported Instance Variable: footSep
footSep is an assignable instance variable containing the
character(s) to separate the footing instance variable from the
bottom data row. Specifying this instance variable will cause the
loss of one more data row.
Example
object:footSep := '─╨─'
TBCOLUMN Exported Instance Variable: heading
heading is an assignable instance variable which when assigned
determines what to display as a heading for a TBCOLUMN object.
The footing will be displayed on the top row of the TBROWSE
object window. Specifying this instance variable will cause the
loss of one data row.
The initial value assigned to this instance variable will be the
value passed as a heading to the TBColumnNew() class function.
Example
object:heading := 'This is a heading'
TBCOLUMN Exported Instance Variable: headSep
headSep is a user assignable instance variable used to define the
character(s) to be used by to separate each column for it's
heading in the TBROWSE display.
The value set in headSep will override the TBROWSE headSep
instance variable.
Example
object:headSep := '─╥─'
TBCOLUMN Exported Instance Variable: width
width is a user assignable instance variable of numeric type to
determine the width of the TBCOLUMN object.
If the value contained in width is greater than the number of
screen column available to the TBROWSE object the width instance
variable will stay at the assigned variable but the display will
only show the maximum width allowed by the TBROWSE object.
Note: If it's value is greater than the length of the value
returned by the block instance variable the width of the
highlight bar will not be increased. To do this the block
instance variable must be modified.
Example
object:width := 25
Power Of TBROWSE Objects
Scoping TBROWSE objects
The main problem of DBEDIT() in Clipper Summer 87 is that is was
difficult to browse a subset of a .DBF file. A lot of code was
needed to perform this task but with TBROWSE objects it has been
made a great deal easier. The handling of TBROWSE objects is user
definable, you tell the TBROWSE object what you want to display
There are several ways of creating scoped TBROWSE objects, some
more easier than others.
Described below are three ways to achieve this.
Method 1
Using the SET FILTER TO command.
Using the SET FILTER TO command is the easiest way of creating
scoped TBROWSE objects. Simply set a filter to a condition and
perform the most simple TBROWSE handling routine ie/ one that
moves the cursor position and allows editing letting the SET
FILTER command handle which records are to be displayed.
ADVANTAGES
1. Easy to create
2. No Indexes Required
DISADVANTAGES
1. Very slow when cursoring out of the scope, especially on large
.DBF files
Method 2
Coding the scope into the user defined function contained in the
code block for the skipBlock, goBottomBlock and goTopBlock
instance variables.
Using this method will require a deeper knowledge of the way
TBROWSE objects work internally. To make the most of this method
an index should be used. For example: If you want a list of
transactions for a particular customer, the transactions file
would have an index built on the customer id.
ADVANTAGES
1. Quick when cursoring out of the scope as using an index will
keep the records in a scoped order.
DISADVANTAGES
1. A different user defined function will be needed for each
different scope.
Example
// Modification of default skipBlock
object:skipBlock := {|x|Skipper(x,lAppend)}
Function Skipper(n,lAppend)
local i
i := 0
If ( LastRec() != 0 )
If ( n == 0 )
SKIP 0
Elseif ( n > 0 .and. Recno() != LastRec() + 1 )
Do While ( i < n )
SKIP 1
If ( Eof() .or. !(condition))
If ( lAppend )
i++
Else
SKIP -1
Endif
Exit
Endif
i++
Enddo
Elseif ( n < 0 )
Do While ( i > n )
SKIP -1
If ( Bof() .or. !(condition))
exit
Endif
i--
Enddo
Endif
Endif
return (i)
Where (condition) would be something like:
CUST_ID == CUSTOMER->CUST_ID
or
(condition) could be a variable which could be macroed.
goTopBlock would simply perform a SEEK to find the first scoped
record.
goBottomBlock would keep SKIPing until it finds the last scoped
record. The best way to do this is to skip in blocks of ten (or
more) until you are out of the scope then SKIP backwards.
Method 3
Coding the scope into the user defined function contained in the
code block for the skipBlock, goBottomBlock and goTopBlock
passing a code block to the user defined function assigned in the
code blocks for skipBlock,goTopBlock and goBottomBlock.
Using this method will require a deep knowledge of the way
TBROWSE objects work internally as well as a good knowledge of
code blocks and their power. To make the most of this method an
index should be used. For example: If you want a list of
transactions for a particular customer, the transactions file
would have an index built on the customer id.
The best way to implement this method is by using the TBROWSE
cargo instance variable.
ADVANTAGES
1. Quick when cursoring out of the scope as using an index will
keep the records in a scoped order.
2. Code blocks are faster than macros (and more powerful).
3. Only ONE user defined function will be required for
skipBlock,goBottomBlock and goTopBlock.
4. Once working the user defined function will never need
changing.
5. The scope can be changed at any time without any code changes.
DISADVANTAGES
1. Not very easy to get right first time.
Example
// Modification of default skipBlock
object:cargo := {||CUST_ID == CUSTOMER->CUST_ID}
object:skipBlock := {|x|Skipper(x,lAppend,object:cargo)}
Function Skipper(n,lAppend,condition_block)
local i
i := 0
If ( LastRec() != 0 )
If ( n == 0 )
SKIP 0
Elseif ( n > 0 .and. Recno() != LastRec() + 1 )
Do While ( i < n )
SKIP 1
If ( Eof() .or. !EVAL(condition_block))
If ( lAppend )
i++
Else
SKIP -1
Endif
Exit
Endif
i++
Enddo
Elseif ( n < 0 )
Do While ( i > n )
SKIP -1
If ( Bof() .or. !EVAL(condition_block))
exit
Endif
i--
Enddo
Endif
Endif
return (i)
There are of course more ways of implementing scoped TBROWSE
objects using macros,code blocks in various ways.
Note: The more code blocks that are used over macros the faster
the TBROWSE will run.
Array TBROWSE Objects
Many Clipper users look upon TBROWSE objects as being a mechanism
of browsing .DBF files and only .DBF files. This is not the case.
TBROWSE objects can be used on elements of an array similar to
the way the ACHOICE() function works but with more power.
To use TBROWSE objects on arrays the code blocks contained in the
skipBlock,goBottomBlock and goTopBlock instance variables must be
modified drastically to handle the display and update of the
array elements.
A great deal more power can be creating multi-dimensional arrays
to handle comments,actions to be performed upon certain keys and
much more.
Example
// Array to browse
array := {'ELEMENT 1','ELEMENT 2','ELEMENT 3','ELEMENT 4'}
current_element := 1
object:=TBROWSENEW(10,10,15,25)
code_block := {|setval|IF(setval==NIL,array[current_element],;
array[current_element] := setval)}
column := TBCOLUMNNEW('Arrays',code_block)
object:addColumn(column)
object:skipBlock := {|x|ArraySkip(x)}
object:goTopBlock := {||ATopBottom(1)}
object:goBottomBlock := {||ATopBottom(Len(Array))}
Function ArraySkip(n)
Local i:=0
If n > 0
Do While n > 0
If current_element +1 <= Len(array)
current_element ++
i ++
n --
Else
Exit
Endif
Enddo
Elseif n < 0
Do While n < 0
If current_element -1 >= 1
current_element --
i --
n ++
Else
Exit
Endif
Enddo
Endif
Return i
Function Atopbottom(x)
current_element := x
Return NIL
One of the advantages of using TBROWSE objects on arrays over the
ACHOICE() function is that each element of the array can be modified
directly.
Column Modifications
The ability to be able to make modifications to a TBCOLUMN object
directly give TBROWSE object a great deal more power than any
function in Clipper.
For example, if you wanted to change the information displayed in
a field using DBEDIT() you must exit the DBEDIT() then re-enter
it. This causes the cursor positions to change. With TBROWSE
objects this does not occur as the columns can be modified
directly. If you change the information to be displayed you
simply issue the reFreshCurrent() exported method and everything
is taken care of.
The same with ACHOICE(). Although with ACHOICE() you can set the
starting positions you still have to exit the ACHOICE() and
re-enter it.
Column Insertion
How many times have users of your applications wanted to be able
to display more information than you have provided but only at
certain times ? Quite often. This is no problem with TBROWSE
objects. Simply create a new TBCOLUMN class and use the
addColumn() exported method to add it to the TBROWSE object.
Column Movement
Wouldn't it be nice to be able to change the order of the columns
in a browse display. With TBROWSE objects this is simple, as long
as these rules are stuck to.
1. Take a copy of the column you want to move using the
getColumn() exported method.
2. Copy the column left or right of the column you want to move
depending on the direction you wish to move the column also using
setColumn() to the position of the column you wish to move.
3. Copy the copy of the column you wish to move into the position
you wish to move it to using the setColumn() exported method.
4. Use the configure() exported method to force the screen to be
refreshed during the next stabilization process.
Use this style and you can't go wrong.
You could also write a user defined command to do this.
Example
#command MOVE COLUMN n LEFT => ;
;
old_column := object:getColumn(n) ;;
object:setColumn(n,object:getColumn(n-1)) ;;
object:setColumn(n-1,old_column)
Examples
REAL examples are being worked on at this moment in time. Keep
you posted.